package cn.aiweiyi.qingjing.coupon.comm.advice;

import cn.aiweiyi.qingjing.coupon.comm.annotation.IgnoreResponseAdice;
import cn.aiweiyi.qingjing.coupon.comm.vo.CommonResponse;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author 青衿
 * @Date 2020/11/14 15:23
 * 实现统一响应的增强,ResponseBodyAdvice接口用于对@ResponseBody
 * 注解的控制器方法进行增强,执行时机是Response写入到客户端浏览器之前
 **/
@RestControllerAdvice
public class CommonResponseAdvice implements
        ResponseBodyAdvice<Object> {

    //实现接口方法,该方法决定了是否要执行增强代码
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
//        如果当前执行的方法标注了@IgnoreResponseAdvice注解,就不执行增强
        if (returnType.getMethod().isAnnotationPresent(IgnoreResponseAdice.class)) {
            return false;
        }
        //如果当前执行的方法所在的类标注了@IgnoreResponseAdvice注解,就不执行增强
        if (returnType.getDeclaringClass().isAnnotationPresent(IgnoreResponseAdice.class)) {
            return false;
        }
        return true;//否则,就执行统一响应的增强
    }

    //实现接口方法,要执行的增强代码
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        CommonResponse result = new CommonResponse();//创建一个统一响应对象
        if (body == null) {
            //如果控制器方法响应未null,也直接返回空对象
            return result;
        } else if (body instanceof CommonResponse) {
            result = (CommonResponse) body;//如果已经是该类型就不做处理
        } else {
            result.setData(body);
            //否则,把该返回的数据封装到统一响应对象
        }
        return result;
    }
}
